//
// Created by Administrator on 2024/1/9.
// 二分答案 木材加工
/*
 * OJ: https://www.luogu.com.cn/problem/P2440  通过
 * 讲解 【《二分答案》信息学竞赛】 https://www.bilibili.com/video/BV1ac411b7BM/?share_source=copy_web&vd_source=039990b6433b5af9bd2905234cc47ac6
 * 二分题单：https://www.luogu.com.cn/contest/135632
 * 题目描述

木材厂有 n 根原木，现在想把这些木头切割成 k 段长度均为 l 的小段木头（木头有可能有剩余）。
当然，我们希望得到的小段木头越长越好，请求出 l 的最大值。
木头长度的单位是 cm，原木的长度都是正整数，我们要求切割得到的小段木头的长度也是正整数。
例如有两根原木长度分别为 11 和 21，要求切割成等长的 6 段，很明显能切割出来的小段木头长度最长为 5。
输入格式
第一行是两个正整数 n,k，分别表示原木的数量，需要得到的小段的数量。
接下来 n 行，每行一个正整数 Li​，表示一根原木的长度。
输出格式
仅一行，即 l 的最大值。
如果连 1cm 长的小段都切不出来，输出 0。
输入输出样例
输入 #1

3 7
232
124
456
输出 #1
114
说明/提示
数据规模与约定
对于 100% 的数据，有 1≤n≤10^5，1≤k≤10^8，1≤Li≤10^8(i∈[1,n])1≤Li​≤10^8(i∈[1,n])。
 * */


#include <iostream>

using namespace std;


// 根据当前的长度cur, 判断能不能切出k段
bool check(const int *p, int n, int cur, int k)
{
    int ret = 0;
    for (int i = 0; i < n; ++i)
    {
        ret += p[i] / cur;
    }
    return ret >= k;
}

int main()
{
    int n, k;
    long long sum = 0;
    cin >> n >> k;
    int arr[n];
    for (int i = 0; i < n; ++i)
    {
        cin >> arr[i];
        sum += arr[i];
//        min=min>arr[i]?arr[i]:min;
    }
//    cout<<min<<endl;
    int average = sum / k;
    // 如果平均长度为0, 那就不能可能按要求截取,直接打印0就行了
    if (average == 0 || check(arr, n, average, k))
    {
        cout<<average;
        return 0;
    }
    int left=1,mid;
    average--;
//    cout<<check(arr, n, 58, k)<<endl;
    while (left<=average)
    {
        mid = left+(average-left)/2;
        // 区间分布: 能,......,能,能(最大),不能,...,不能
        if(check(arr, n, mid, k) )
        {
            if (!check(arr, n, mid+1, k))
            {
                // 如果下一个长度不能按要求切割, 说明当前的就是最长的, 跳出循环即可
                break;
            }
            left=mid+1;
        }else{
            average=mid-1;
        }
    }
    cout << mid << endl;

    return 0;
}